/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.service.time.ntptime;

import java.util.Date;

import cgl.narada.service.ServiceException;
import cgl.narada.service.time.TimeService;

/**
 * This class is a singleton class and should be used to retun the adjusted
 * time value. NTP protocol implementation receives time from this class. The
 * only method implemented in this class is getTime(), which should be used to
 * get the adjusted current time.
 *
 * @author Hasan Bulut  - hbulut@indiana.edu
 */
public class TimeServiceImpl implements TimeService {
  //~ Static fields/initializers -----------------------------------------------

  private static TimeServiceImpl instance = new TimeServiceImpl();

  //~ Instance fields ----------------------------------------------------------

  private ServiceException serviceException = null;
  private long             delta       = 0;
  private long             lastUTCTime = 0;
  private long             offset      = 0;

  //~ Constructors -------------------------------------------------------------

  /**
   * Generates a new TimeServiceImpl object.
   */
  private TimeServiceImpl() {
  }

  //~ Methods ------------------------------------------------------------------

  /**
   * Gets the only instance of TimeServiceImpl.
   *
   * @return TimeServiceImpl - this object
   */
  public static TimeServiceImpl getInstance() {
    return instance;
  }

  /**
   * Gets the last change in the offset value
   *
   * @return long - last change in the offset value
   */
  public long getDelta() {
    return delta;
  }

  /**
   * Adjusts the offset value by delta. If the new time value would be less than
   * the last time value provided, it is not updated.
   *
   * @param offDelta - adjustment to be made to offset
   */
  public void setOffset(long offDelta) {
    long temp = (new Date()).getTime() + offset;
    if (NtpTimeService.isCheckLastUTC()) {
      if (lastUTCTime > (temp + offDelta)) {
        return;
      }
    }
    delta  = offDelta;
    offset = offset + offDelta;
  }

  /**
   * Gets offset value between the local computer's time and the computed time
   * from NTP protocol.
   *
   * @return long - offset value
   */
  public long getOffset() {
    return offset;
  }

  /**
   * Sets exception
   *
   * @param serviceException
   */
  public void setServiceException(ServiceException serviceException) {
    this.serviceException = serviceException;
  }

  /**
   * Returns ServiceException
   *
   * @return ServiceException
   */
  public ServiceException getServiceException() {
    return serviceException;
  }

  /**
   * Gets adjusted time
   *
   * @return long - adjusted time in milliseconds
   */
  public long getTimestamp() throws ServiceException {
    if (serviceException != null) {
      throw serviceException;
    }
    long utcTime = (new Date()).getTime() + offset;
    lastUTCTime = utcTime;
    return utcTime;
  }
}
